package com.hksj.gas.service;


import cn.hutool.core.util.ObjectUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.write.metadata.style.WriteCellStyle;
import com.alibaba.excel.write.style.column.LongestMatchColumnWidthStyleStrategy;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.gson.*;
import com.google.gson.reflect.TypeToken;
import com.hksj.base.service.DefaultDeviceService;
import com.hksj.cbm.util.CellStyleStrategy;
import com.hksj.cbm.util.CustomCellWriteHandler;
import com.hksj.cbm.util.DateTimeFormatUtil;
import com.hksj.cbm.util.PageListUtils;
import com.hksj.common.core.common.SpecialityModelCodeEnum;
import com.hksj.gas.dto.GasDeviceDTO;
import com.hksj.gas.dto.GasDeviceDetailsDTO;
import com.hksj.gas.mapper.GasDeviceMapper;
import com.hksj.gas.vo.*;

import com.hksj.tdengine.taos.service.TaosService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;


import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.Type;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.IntStream;


@Service
public class GasDeviceService {

    private static final Logger log = LoggerFactory.getLogger(GasDeviceService.class);

    @Autowired
    private GasDeviceMapper gasDeviceMapper;

    @Autowired
    private DefaultDeviceService defaultDeviceService;

    @Autowired
    private TaosService taosService;

    /**
     * 根据条件分页查询气体设备压力的详细信息。
     *
     * @param dto 查询条件对象，包含分页信息和设备相关条件。
     * @return 返回分页查询结果，包含气体设备的详细信息。
     */
    public IPage<GasDeviceVO> queryPressureGasDeviceListByPage(GasDeviceDTO dto) {
        //添加专业code
        dto.setCode(SpecialityModelCodeEnum.medical_gas.getCode());
        // 初始化分页对象，传入当前页码和每页大小
        IPage<GasDeviceVO> page = new Page<>(dto.getPageNum(), dto.getPageSize());
        // 调用Mapper查询符合条件的气体设备列表
        List<GasDeviceVO> list = gasDeviceMapper.queryPressureGasDeviceListByPage(page, dto);

        //非空判断
        if (CollectionUtils.isEmpty(list)) {
            return page;
        }

        //查询tdengine数据库
        Map<String,List<GasDeviceVO>> map =list.stream().collect(Collectors.groupingBy(GasDeviceVO::getProductId));
        List<GasDeviceVO> dailyFlowAllList = new ArrayList<>();
        for (Map.Entry<String, List<GasDeviceVO>> entry : map.entrySet()) {
            try {
                String tableName = defaultDeviceService.getTableName(entry.getKey());
                List<String> deviceIdList = entry.getValue().stream().map(GasDeviceVO::getDeviceId).collect(Collectors.toList());
                List<GasDeviceVO> dailyList = gasDeviceMapper.queryHistoryDeviceDaily(deviceIdList, tableName, dto);
                dailyFlowAllList.addAll(dailyList);
            } catch (Exception e) {
                log.error("查询tdengine数据库失败", e);
            }
        }

        //set值到list
        Map<String, Double> dailyFlowMap= dailyFlowAllList.stream().collect(Collectors.toMap(GasDeviceVO::getDeviceId, GasDeviceVO::getAvgPressure));
        list.forEach(item -> {
            Double avgPressure = dailyFlowMap.get(item.getDeviceId());
            if (!ObjectUtils.isEmpty(avgPressure)) {
                item.setAvgPressure((double) Math.round(avgPressure * 100) / 100);
            }
            if (Objects.equals(item.getState(), "offline")) {
                item.setPressure(null);
                item.setAvgPressure(null);
            }
        });

        page.setRecords(list);
        return page;
    }

    /**
     * 根据条件分页查询气体设备流量的详细信息。
     *
     * @param dto 查询条件对象，包含分页信息和设备相关条件。
     * @return 返回分页查询结果，包含气体设备的详细信息。
     */
    public IPage<GasDeviceVO> queryFlowGasDeviceListByPage(GasDeviceDTO dto) {
        //添加专业code
        dto.setCode(SpecialityModelCodeEnum.medical_gas.getCode());
        //当日流量排序特殊处理
        if (Objects.equals(dto.getOrder(), "3")) {
            return queryGasDeviceFlowByPage(dto);
        }

        // 初始化分页对象，传入当前页码和每页大小
        IPage<GasDeviceVO> page = new Page<>(dto.getPageNum(), dto.getPageSize());
        List<GasDeviceVO> list = gasDeviceMapper.queryFlowGasDeviceListByPage(page, dto);

        //非空判断
        if (CollectionUtils.isEmpty(list)) {
            return page;
        }
        //查询tdengine数据库
        Map<String,List<GasDeviceVO>> map =list.stream().collect(Collectors.groupingBy(GasDeviceVO::getProductId));
        List<GasDeviceVO> dailyFlowAllList = new ArrayList<>();
        //查询不同产品下的id
        for (Map.Entry<String, List<GasDeviceVO>> entry : map.entrySet()) {
            try {
                String tableName = defaultDeviceService.getTableName(entry.getKey());
                List<String> deviceIdList = entry.getValue().stream().map(GasDeviceVO::getDeviceId).collect(Collectors.toList());
                List<GasDeviceVO> dailyList = gasDeviceMapper.queryFlowHistoryDeviceDaily(deviceIdList, tableName, dto);
                dailyFlowAllList.addAll(dailyList);
            } catch (Exception e) {
                log.error("查询tdengine数据库失败", e);
            }
        }
        Map<String, Double> dailyFlowMap= dailyFlowAllList.stream().collect(Collectors.toMap(GasDeviceVO::getDeviceId, GasDeviceVO::getGasDailyFlow));
        list.forEach(item -> {
            Double gasDailyFlow = dailyFlowMap.get(item.getDeviceId());
            if (!ObjectUtils.isEmpty(gasDailyFlow)) {
                item.setGasDailyFlow((double) Math.round(gasDailyFlow * 100) / 100);
            }
            if (Objects.equals(item.getState(), "offline")) {
                item.setGasDailyFlow(null);
                item.setGasCumulativeFlow(null);
            }
        });
        page.setRecords(list);
        return page;
    }

    /**
     * 查询设备压力趋势。
     *
     * @return 返回气体设备的详细信息，包含时间戳和压力值。
     */
    public IPage<GasDeviceTimeVO> queryDeviceDetailsList(GasDeviceDetailsDTO dto){
        IPage<GasDeviceTimeVO> page = new Page<>(dto.getPageNum(), dto.getPageSize());
        String tableName = defaultDeviceService.getTableName(dto.getProductId());

        List<GasDeviceTimeVO> list = new ArrayList<>();
        Long total = 0L;
        try {
            if(dto.getPageNum()>0) {
                dto.setPageNum((dto.getPageNum() - 1)*dto.getPageSize());
            }
            list = gasDeviceMapper.queryPressureDeviceList(dto,tableName);
            if(!CollectionUtils.isEmpty(list)){
                list.forEach(item -> item.setTs(item.getTs().split("\\.")[0]));
            }
            total = gasDeviceMapper.queryPressureDeviceCount(dto,tableName);
        }catch (Exception e){
            log.error("查询tdengine数据库失败", e);
        }
        page.setRecords(list);
        page.setTotal(total);
        return page;
    }

    /**
     * 查询设备流量使用趋势。
     *
     * @return 返回气体设备的详细信息，包含时间戳和流量使用值。
     */
    public IPage<GasDeviceTimeVO> queryFlowDeviceList(GasDeviceDetailsDTO dto) {
        // 用于存储时间列表
        List<String> timeList = new ArrayList<>();

        // 根据周期类型生成相应的时间列表
        if (ObjectUtil.equals(dto.getTimeCycle(), "1")) {
            // 天周期
            timeList = DateTimeFormatUtil.getDayList(dto.getStartTime(), dto.getEndTime());
        } else if (ObjectUtil.equals(dto.getTimeCycle(), "2")) {
            // 月周期
            timeList = DateTimeFormatUtil.getMonthList(dto.getStartTime(), dto.getEndTime());
        }

        // 生成时间列表
        List<GasDeviceTimeVO> list = timeList.stream().map(time -> {
                    GasDeviceTimeVO waterDeviceCountVO = new GasDeviceTimeVO();
                    waterDeviceCountVO.setTs(time);
                    return waterDeviceCountVO;
                })
                .collect(Collectors.toList());
        //生成超级表名称
        String tableName = defaultDeviceService.getTableName(dto.getProductId());

        try {
            List<GasDeviceTimeVO> result = gasDeviceMapper.queryFlowDeviceList(dto,tableName);
            if (!CollectionUtils.isEmpty(result)) {
                Map<String, GasDeviceTimeVO> map = result.stream().collect(Collectors.toMap(GasDeviceTimeVO::getTs, item -> item));
                list.forEach(item -> {
                    if (map.containsKey(item.getTs())){
                        Double value = map.get(item.getTs()).getVal();
                        item.setVal(Math.round(value * 100.0) / 100.0);
                    }
                });
            }
        } catch (Exception e) {
            log.error("查询tdengine数据库失败", e);
        }

        return PageListUtils.getPages(dto.getPageNum().intValue(), dto.getPageSize().intValue(), list);
    }

    public void exportPressureDeviceInfo(GasDeviceDetailsDTO dto, HttpServletResponse response) throws Exception {
        dto.setPageNum(null);
        dto.setPageSize(null);
        String tableName = defaultDeviceService.getTableName(dto.getProductId());
        List<GasDeviceTimeVO> list = gasDeviceMapper.queryPressureDeviceList(dto,tableName);

        //封装导出数据
        List<ExportGasDeviceVO> exportList = new ArrayList<>();
        if (!CollectionUtils.isEmpty(list)){
            exportList = IntStream.range(0, list.size())
                    .mapToObj(index -> {
                        GasDeviceTimeVO energyHistory = list.get(index);
                        ExportGasDeviceVO vo = new ExportGasDeviceVO();
                        vo.setSeq(index + 1);
                        vo.setVal(Double.valueOf(energyHistory.getVal()));
                        vo.setTs(energyHistory.getTs().split("\\.")[0]);
                        return vo;
                    })
                    .collect(Collectors.toList());
        }

        //封装表头
        List<List<String>> header= new ArrayList<>();
        header.add(Collections.singletonList("序号"));
        header.add(Collections.singletonList("压力值（Mpa）"));
        header.add(Collections.singletonList("上报时间"));

        String fileName = new StringBuffer()
                .append("设备压力趋势")
                .append(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
                        .format(new Date()))
                .append(".xlsx")
                .toString();

        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(fileName, "UTF-8"));

        EasyExcel.write(response.getOutputStream())
                .registerWriteHandler(new CustomCellWriteHandler())
                .registerWriteHandler(new CellStyleStrategy(Collections.singletonList(0),new WriteCellStyle(), new WriteCellStyle()))
                .head(header)
                .sheet("sheet1")
                .doWrite(exportList);
    }

    public void exportFlowDeviceInfo(GasDeviceDetailsDTO dto,HttpServletResponse response) throws Exception{
        List<GasDeviceTimeVO> list = queryFlowDeviceList(dto).getRecords();

        //封装导出数据
        List<ExportGasDeviceVO> exportList = new ArrayList<>();
        if (!CollectionUtils.isEmpty(list)){
            exportList = IntStream.range(0, list.size())
                    .mapToObj(index -> {
                        GasDeviceTimeVO energyHistory = list.get(index);
                        ExportGasDeviceVO vo = new ExportGasDeviceVO();
                        vo.setSeq(index + 1);
                        vo.setVal(Double.valueOf(energyHistory.getVal()));
                        vo.setTs(energyHistory.getTs());
                        return vo;
                    })
                    .collect(Collectors.toList());
        }

        //封装表头
        List<List<String>> header= new ArrayList<>();
        header.add(Collections.singletonList("序号"));
        header.add(Collections.singletonList("流量值(m³)"));
        header.add(Collections.singletonList("统计时间"));

        String fileName = new StringBuffer()
                .append("设备流量使用趋势")
                .append(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
                        .format(new Date()))
                .append(".xlsx")
                .toString();

        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(fileName, "UTF-8"));
        EasyExcel.write(response.getOutputStream())
                .registerWriteHandler(new CustomCellWriteHandler())
                .registerWriteHandler(new CellStyleStrategy(Collections.singletonList(0),new WriteCellStyle(), new WriteCellStyle()))
                .head(header)
                .sheet("sheet1")
                .doWrite(exportList);

    }

    /**
     * 分页查询设备流量数据
     *
     * @param dto 查询参数对象
     * @return 分页的设备流量数据
     */
    public IPage<GasDeviceVO> queryGasDeviceFlowByPage(GasDeviceDTO dto) {
        // 从数据库中查询设备流量数据列表
        List<GasDeviceVO> list = gasDeviceMapper.queryFlowGasDeviceListByPage(null, dto);
        // 如果查询结果为空，则返回一个空的分页对象
        if (CollectionUtils.isEmpty(list)) {
            return new Page<>();
        }
        // 将查询结果按照产品ID分组
        Map<String,List<GasDeviceVO>> map =list.stream().collect(Collectors.groupingBy(GasDeviceVO::getProductId));
        // 用于存储所有设备的日流量数据
        List<GasDeviceVO> dailyFlowAllList = new ArrayList<>();
        // 遍历每个产品ID对应的设备流量数据
        for (Map.Entry<String, List<GasDeviceVO>> entry : map.entrySet()) {
            try {
                // 根据产品ID构造数据库表名
                String tableName = defaultDeviceService.getTableName(entry.getKey());
                // 获取当前产品下所有设备的设备ID列表
                List<String> deviceIdList = entry.getValue().stream().map(GasDeviceVO::getDeviceId).collect(Collectors.toList());
                // 查询当前产品下所有设备的日流量数据
                List<GasDeviceVO> dailyList = gasDeviceMapper.queryFlowHistoryDeviceDaily(deviceIdList, tableName, dto);
                // 将查询到的日流量数据添加到总列表中
                dailyFlowAllList.addAll(dailyList);
            } catch (Exception e) {
                // 如果查询数据库出错，则记录错误日志
                log.error("查询tdengine数据库失败", e);
            }
        }
        // 将所有设备的日流量数据存储到一个Map中，以便后续快速查询
        Map<String, Double> dailyFlowMap= dailyFlowAllList.stream().collect(Collectors.toMap(GasDeviceVO::getDeviceId, GasDeviceVO::getGasDailyFlow));
        // 为每个设备设置日流量数据
        list.forEach(item -> item.setGasDailyFlow(dailyFlowMap.get(item.getDeviceId())));
        // 根据排序参数对设备流量数据进行排序
        if (Objects.equals(dto.getSort(), "1")) {
            list.sort(Comparator.comparing(GasDeviceVO::getGasDailyFlow));
        } else {
            list.sort(Comparator.comparing(GasDeviceVO::getGasDailyFlow).reversed());
        }
        // 根据分页参数返回分页后的设备流量数据
        return PageListUtils.getPages(dto.getPageNum().intValue(), dto.getPageSize().intValue(), list);
    }


}
